#include "until.h"
#include <signal.h>
#include <memory.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>

// https://blog.csdn.net/changli_90/article/details/8926769
// https://blog.csdn.net/chengqiuming/article/details/88934534
void handleForSigpipe()
{
    struct sigaction sa;
    memset(&sa, '\0', sizeof(sa));
    sa.sa_handler = SIG_IGN;
    sa.sa_flags = 0;
    if(sigaction(SIGPIPE, &sa, NULL))
        return;

}

/**
 * 信号获取、设置处理 设置为非阻塞模式
 * @brief sigactionInit
 * @param fd
 * @return
 */
int sigactionInit(int fd)
{
    int flag = fcntl(fd, F_GETFL, 0);
    if(flag == -1) {
        perror("信号初始化失败");
        return -1;
    }
    flag |= O_NONBLOCK;
    if(fcntl(fd, F_SETFL, flag) == -1)
        return -1;
    return 0;
}

int setSocketAndBindListen(unsigned short port)
{
    if (port > 65335) {
        perror("端口过大，不得超过65335");
        return -1;
    }

    // 设置socket
    int socketResult = socket(AF_INET, SOCK_STREAM, 0);

    if (-1 == socketResult) {
        perror("设置socket 失败");

        return -1;
    }

    // 清除bind时 fix Already use bind 错误
    int opval = 1;

    if (-1 == setsockopt(socketResult, SOL_SOCKET, SO_REUSEADDR, &opval, sizeof (opval)))
    {
        perror("清除bind时 fix Already use bind 错误时失败");

        return -1;
    }

    // bind socket

    struct sockaddr_in sock;

    memset(&sock, '0', sizeof(sock));


    sock.sin_family = AF_INET;

    sock.sin_addr.s_addr = htonl(INADDR_ANY);

    sock.sin_port = htons(port);

    int bindSocket = bind(socketResult, reinterpret_cast<sockaddr*>(&sock), sizeof (sock));

    if (-1 == bindSocket) {
        perror("socket 绑定失败");
        return -1;
    }

    // 监听
    int listenr = listen(socketResult, 2048);

    if (-1 == listenr) {
        perror("监听失败");
        return -1;
    }

    // 无效监听描述符
    if(-1 == listenr)
    {
        close(listenr);
        return -1;
    }
    return socketResult;

}

void setSocketNodelay(int fd)
{
    int enable = 1;
    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable));
}

void shutDownWR(int fd)
{
    shutdown(fd, SHUT_WR);
    //printf("shutdown\n");
}
